package com.bitoon.basketdudes.web.xhr;

import com.bitoon.basketdudes.web.BaseAction;
import com.bitoon.basketdudes.web.jpa.Usuario;
import com.bitoon.basketdudes.web.datos.InfoCabeceraXHR;

import java.util.*;
import javax.persistence.*;
import org.apache.log4j.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ListaManagers extends BaseAction {
    
    private List<Usuario> datos;
    private InfoCabeceraXHR cabecera;
    private int pagina = 1;
    private int cuantos;

    // Parámetros de búsqueda por letras
    private String letras;

    // Parámetros del filtrado
    private String modificador_historico;
    private String modificador_media;
    private String modificador_nivel;
    private String modificador_posicion;
    private String numero_historico;
    private String numero_media;
    private String numero_nivel;
    private String numero_posicion;

    // Parámetros de búsqueda de cadena
    private String cadena;

    private Logger log = Logger.getLogger(ListaManagers.class);

    public String execute() {

        try {
            // El método sólo se ejecuta al principio, la paginación va por consultaXhr

            String letraDesde = "";
            String letraHasta = "";

            if (modificador_historico != null) {
                // Filtrado
                //buscaUsuarios("d", "e", true);
            } else if (cadena != null) {

                if (cadena.length() >= 3) {
                    // Poner la cadena en sesion para futuras busquedas
                    session.remove("btn_manager_letraDesde");
                    session.remove("btn_manager_letraHasta");
                    session.put("btn_manager_cadena", cadena);

                    // Búsqueda por cadena, con o num de registros a visualizar personalizado
                    if(cuantos==0){
                        buscaUsuarios(cadena);
                    }else{
                        //compruebo si la cadena pasada por parámetro hay que buscarla por email o por nick
                        log.debug("Busco por email = "+comprobarSiesEmail(cadena));
                        if(comprobarSiesEmail(cadena)==true){
                            buscaUsuarios(cadena, cuantos, LISTADO_MANAGERS_HUECOS_LADO_PAGINA,true);
                        }else{
                            buscaUsuarios(cadena, cuantos, LISTADO_MANAGERS_HUECOS_LADO_PAGINA,false);
                        }
                    }
                }
            } else {
                // Acceso por defecto, navegación
                if (letras != null) {
                    if (letras.length() == 3) {
                        letraDesde = letras.substring(0,1);
                        letraHasta = letras.substring(2,3);
                    } else if (letras.equals("todos")) {
                        letraDesde = "a";
                        letraHasta = "z";
                    }

                    // Grabar en sesion las letras, para futuras busquedas
                    session.put("btn_manager_letraDesde", letraDesde);
                    session.put("btn_manager_letraHasta", letraHasta);
                    session.remove("btn_manager_cadena");

                } else {
                    letras="";
                }
                if (letras!=null && letras!="") {
                    buscaUsuarios(letraDesde, letraHasta, true);
                }
            }
        } catch (Exception e) {
            log.error("Error", e);
        }

        return SUCCESS;
    }

    public String consultaXhr() {

        // Ver si hay cadena o letras en sesion
        if (session.get("btn_manager_cadena") != null) {
            buscaUsuarios((String)session.get("btn_manager_cadena"));
        } else if (session.get("btn_manager_letraDesde") != null) {
            buscaUsuarios((String)session.get("btn_manager_letraDesde"),
                    (String)session.get("btn_manager_letraHasta"), false);
        }

        return SUCCESS;
    }

    public String adminXhr() {
        //este método es para la parte de administracion
        String retorno = null;
        boolean email = false;
        // Si han pasado el parametro cadena
        if (cadena!=null)
        {
            //compruebo si la cadena pasada por parámetro si hay que buscar por email o por nick
            log.debug("Busco por email = "+comprobarSiesEmail(cadena));
            if(comprobarSiesEmail(cadena)==true){
                buscaUsuarios(cadena, cuantos, LISTADO_MANAGERS_HUECOS_LADO_PAGINA,true);
            }else{
                buscaUsuarios(cadena, cuantos, LISTADO_MANAGERS_HUECOS_LADO_PAGINA,false);
            }
            retorno = SUCCESS;
        }

        return retorno;
    }

    private boolean comprobarSiesEmail(String cadena){
        Pattern pat = null;
        Matcher mat = null;
        log.debug("Entro a comprobar el email");
        pat = Pattern.compile("^([0-9a-zA-Z]([_.w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-w]*[0-9a-zA-Z].)+([a-zA-Z]{2,9}.)+[a-zA-Z]{2,3})$");
        mat = pat.matcher(cadena);
        if (mat.find()) {
            log.debug("[" + mat.group() + "]");
            return true;
        }else{
            return false;
        }
    }

    private void buscaUsuarios() {
        buscaUsuarios("a","c",true);
    }

    private void buscaUsuarios(String cadena) {
        buscaUsuarios(cadena, LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA, LISTADO_MANAGERS_HUECOS_LADO_PAGINA,false);
    }

    private void buscaUsuarios(String cadena, int elementos, int huecos,boolean email) {
        List<Usuario> retorno = null;
        EntityManager em = null;

        try {
            log.debug("Buscando " + cadena);
            retorno = new ArrayList<Usuario>();

            em = emfBasket.createEntityManager(); // checked

            Query qc;
            //si hay que buscar por email o por nick
            if(email){
                log.debug("Busco por email");
                qc = em.createNativeQuery("SELECT * FROM central.usuario WHERE LOWER(email) LIKE :nombre", Usuario.class);
            }else{
                log.debug("Busco por nick");
                qc = em.createNativeQuery("SELECT * FROM central.usuario WHERE LOWER(nick) LIKE :nombre", Usuario.class);
            }
            qc.setParameter("nombre", "%" + cadena.toLowerCase() + "%");

            int totalRegistros = qc.getResultList().size();
            log.debug("totalRegistros: " + totalRegistros);
            int totalPaginas = (totalRegistros-1)/elementos + 1;

            int offset = (pagina-1) * elementos;
            int first = (pagina-1)*elementos; //primer registro
            int max = elementos; //ultimo registro
            
            Query q;
            if(email){
                q = em.createNativeQuery("SELECT * FROM central.usuario WHERE LOWER(email) LIKE :nombre", Usuario.class);
            }else{
                q = em.createNativeQuery("SELECT * FROM central.usuario WHERE LOWER(nick) LIKE :nombre", Usuario.class);
            }
            q.setParameter("nombre", "%" + cadena.toLowerCase() + "%");
            q.setFirstResult(first);
            q.setFirstResult(offset);
            q.setMaxResults(max);

            retorno = (List<Usuario>)q.getResultList();

            log.debug("retorno: " + retorno.size());

            cabecera = new InfoCabeceraXHR();
            cabecera.setCorrecto(1);
            cabecera.setActual(pagina);
            cabecera.setTotal(totalPaginas);

            int p1=0, p2=0;

            if (pagina <= (huecos+1)) {
                p1 = 1;
                p2 = huecos*2 + 1;
            } else if (pagina >= (totalPaginas-huecos)) {
                p1 = totalPaginas - (huecos*2);
                p2 = totalPaginas;
            } else {
                p1 = pagina - huecos;
                p2 = pagina + huecos;
            }
            if (p1 < 1) {
                p1 = 1;
            }
            if (p2 > totalPaginas) {
                p2 = totalPaginas;
            }
            cabecera.setPrimeraPagina(p1);
            cabecera.setUltimaPagina(p2);

            setDatos(retorno);
            setCabecera(cabecera);

        } catch (Exception e) {
            log.error("[buscaUsuarios(String)]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }
    }

    private void buscaUsuarios(String letraDesde, String letraHasta, boolean cambiarHasta) {
        List<Usuario> retorno = null;
        EntityManager em = null;

        try {

            retorno = new ArrayList<Usuario>();

            log.debug("pagina: " + pagina);
            
            em = emfBasket.createEntityManager(); // checked

            // Hacer que la letraHasta sea la siguiente a la pasada. Si es c, que sea d; si es o, que sea p; etc.

            if (cambiarHasta) {
                if (letras!=null && !letras.equals("todos")) {
                    char l = letraHasta.charAt(0);
                    int c = (int)l;
                    l = (char)(l+1);
                    letraHasta = "" + l;
                }

                log.debug("letraHasta: " + letraHasta);
            }


            Query qc = em.createNamedQuery("Usuario.findByFirstLetters");
            qc.setParameter("letraDesde", letraDesde);
            qc.setParameter("letraHasta", letraHasta);

            int totalRegistros = qc.getResultList().size();
            int totalPaginas = (totalRegistros-1)/LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA + 1;

            int offset = (pagina-1) * LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA;
            
            Query q = em.createNamedQuery("Usuario.findByFirstLetters");
            q.setParameter("letraDesde", letraDesde);
            q.setParameter("letraHasta", letraHasta);
            q.setFirstResult((pagina-1)*LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA);
            q.setFirstResult(offset);
            log.debug("maxresults: " + LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA);
            q.setMaxResults(LISTADO_MANAGERS_ELEMENTOS_POR_PAGINA);

            retorno = (List<Usuario>)q.getResultList();

            cabecera = new InfoCabeceraXHR();
            cabecera.setCorrecto(1);
            cabecera.setActual(pagina);
            cabecera.setTotal(totalPaginas);

            int p1=0, p2=0;

            if (pagina <= (LISTADO_MANAGERS_HUECOS_LADO_PAGINA+1)) {
                p1 = 1;
                p2 = LISTADO_MANAGERS_HUECOS_LADO_PAGINA*2 + 1;
            } else if (pagina >= (totalPaginas-LISTADO_MANAGERS_HUECOS_LADO_PAGINA)) {
                p1 = totalPaginas - (LISTADO_MANAGERS_HUECOS_LADO_PAGINA*2);
                p2 = totalPaginas;
            } else {
                p1 = pagina - LISTADO_MANAGERS_HUECOS_LADO_PAGINA;
                p2 = pagina + LISTADO_MANAGERS_HUECOS_LADO_PAGINA;
            }
            if (p1 < 1) {
                p1 = 1;
            }
            if (p2 > totalPaginas) {
                p2 = totalPaginas;
            }
            cabecera.setPrimeraPagina(p1);
            cabecera.setUltimaPagina(p2);

            setDatos(retorno);
            setCabecera(cabecera);

        } catch (Exception e) {
            log.error("[buscaUsuarios]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

    }

    public String getLetras() {
        return letras;
    }

    public void setLetras(String letras) {
        this.letras = letras;
    }

    public List<Usuario> getDatos() {
        return datos;
    }

    public void setDatos(List<Usuario> resultadoBusqueda) {
        this.datos = resultadoBusqueda;
    }

    public int getPagina() {
        return pagina;
    }

    public void setPagina(int pagina) {
        this.pagina = pagina;
    }

    public int getCuantos() {
        return cuantos;
    }

    public void setCuantos(int cuantos) {
        this.cuantos = cuantos;
    }

    public InfoCabeceraXHR getCabecera() {
        return cabecera;
    }

    public void setCabecera(InfoCabeceraXHR cabecera) {
        this.cabecera = cabecera;
    }

    public String getModificador_historico() {
        return modificador_historico;
    }

    public void setModificador_historico(String modificador_historico) {
        this.modificador_historico = modificador_historico;
    }

    public String getModificador_media() {
        return modificador_media;
    }

    public void setModificador_media(String modificador_media) {
        this.modificador_media = modificador_media;
    }

    public String getModificador_nivel() {
        return modificador_nivel;
    }

    public void setModificador_nivel(String modificador_nivel) {
        this.modificador_nivel = modificador_nivel;
    }

    public String getModificador_posicion() {
        return modificador_posicion;
    }

    public void setModificador_posicion(String modificador_posicion) {
        this.modificador_posicion = modificador_posicion;
    }

    public String getNumero_historico() {
        return numero_historico;
    }

    public void setNumero_historico(String numero_historico) {
        this.numero_historico = numero_historico;
    }

    public String getNumero_media() {
        return numero_media;
    }

    public void setNumero_media(String numero_media) {
        this.numero_media = numero_media;
    }

    public String getNumero_nivel() {
        return numero_nivel;
    }

    public void setNumero_nivel(String numero_nivel) {
        this.numero_nivel = numero_nivel;
    }

    public String getNumero_posicion() {
        return numero_posicion;
    }

    public void setNumero_posicion(String numero_posicion) {
        this.numero_posicion = numero_posicion;
    }

    public String getCadena() {
        return cadena;
    }

    public void setCadena(String cadena) {
        this.cadena = cadena;
    }

}
